#References: http://www.ibm.com/developerworks/aix/library/au-threadingpython/
#            http://code.activestate.com/recipes/577187-python-thread-pool/
#            http://www.mail-archive.com/sqlalchemy@googlegroups.com/msg15665.html

import Queue, threading, urllib2, time

class Worker(threading.Thread):
    """Thread executing tasks from a given tasks queue"""
    def __init__(self, session, queue, num):
        threading.Thread.__init__(self)
        self.num = num
        self.queue = queue
        self.setDaemon(True)
        self.session = session

    def run(self):
        import traceback
        while True:
            func, args, kargs = self.queue.get()
            try:
                func(*args, **kargs)
            except:
                traceback.print_exc()
            self.queue.task_done()

class ThreadPool:
    """Pool of threads consuming tasks from a queue"""
    def __init__(self, session, num_threads):
        from geno import Geno_Shard
        self.queue = Queue.Queue()
        self.workerlist = []
        self.num = num_threads
        self.session = session
        for i in range(num_threads):
            self.workerlist.append(Worker(session, self.queue, i))

    def add_task(self, func, *args, **kargs):
        """Add a task to the queue"""
        self.queue.put((func, args, kargs))

    def start(self):
        for w in self.workerlist:
            w.start()

    def wait_completion(self):
        """Wait for completion of all the tasks in the queue"""
        self.queue.join()
